/********************************************************************

Write Date: 2011/06/02
Author: Deng Nianchen
>>>> Implement OOPObject

Modify Date: 2011/07/16
Author: Deng Nianchen
>>>> Fix bugs on handling operator new[]

Modify Date: 2012/12/01
Author: Deng Nianchen
>>>> Make OOPObject thread-safe
>>>> Reimplement array creating operation
*********************************************************************/
#ifndef OOP_OBJECT_H
#define OOP_OBJECT_H
#include "OOPUtilsGlobal.hpp"

_OOPUTILS_BEGIN

class OOPPtrHelper;

/**************************************************************************************************
 * <summary> Purpose: OOPObject is the root class of all classes in this
 * 					 framework. It provides support for strong smart pointer
 * 					 OOPPtr by recording reference number and whether it's on
 * 					 the heap or stack. Thus all limits in using HeapPtr are
 * 					 removed if you use OOPPtr with object of OOPObject.
 * 					 I recommend you to let your classes inherit OOPObject to
 * 					 gain the advantages of OOPPtr. It will let you feel free
 * 					 with C/C++ pointer.
 * 					 Note that operator new[] is not supported. To dynamically
 * 					 create an OOPObject array, use OOPPtr::newArray().
 * 					 Thread-Safe: the class is thread-safe. </summary>
 *
 * <remarks>  Deng Nianchen, 2012/12/01. </remarks>
 **************************************************************************************************/

class _EXPORT_UTILS_CLASS OOPObject
{

	friend class OOPPtrHelper;

public:

	enum AllocInfo { ON_STACK, ON_HEAP, ARRAY_ON_HEAP };

	OOPObject ();

	OOPObject (const OOPObject &obj);

	virtual ~OOPObject ();

	OOPObject &operator= (const OOPObject &right);

	static void * operator new (size_t size);

	bool isOnHeap () const;

	bool isArrOnHeap () const;

	int getRefNum () const;

	const OOPObject *getRefAffectObj () const;

	template< class T >
	static void newArray (T **pArrayPtr, size_t elemNum);

	static void operator delete[] (void *ptr, size_t elemNum, size_t elemSize);
	static void operator delete[] (void *ptr);

private:

	AllocInfo _allocInfo;

	int _refNum;

	OOPObject * _pRefAffectObj;

	static void * operator new[] (size_t size);
	static void * operator new[] (size_t size, size_t elemNum, size_t elemSize);

};
_OOPUTILS_END

template< class T >
void OOPUtils::OOPObject::newArray (T **pArrayPtr, size_t elemNum)
{
	(*pArrayPtr) = new(elemNum, sizeof(T)) T[elemNum];
}

#endif